﻿using HslCommunication;
using NetCore8Demo.Models.Communication.SerialPortFolder;
using NetCore8Demo.ViewModels.PLC;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Text;

namespace NetCore8Demo.ViewModels.Communication.SerialPortFolder
{
    public  class SerialPortTool
    {


        #region 变量定义
        private SerialPortInfo _serialPortInfo = new SerialPortInfo();
        private SerialPort _serialPort = new SerialPort();
        public bool RecDataFlag;
       
        public int WaitTime = 3000;
       
        public string RecData = "";
        #endregion


        #region 初始化

        public SerialPortTool()
        {

        }

        public SerialPortTool(SerialPortInfo serialPortInfo)
        {
            _serialPortInfo = serialPortInfo;
            _serialPort.DataReceived += SerialPortPortDataReceived;
        }

        #endregion


        #region 主要方法

        //打开串口
        public OperateResult OpenSerialPort()
        {
            OperateResult result = new OperateResult();


            if(!StaticSerialPort.GetAllPortName().Contains(_serialPortInfo.PortName))
            {
                result.IsSuccess = false;
                result.Message = "串口不存在";
                return result;
            }

            if (!_serialPortInfo.IsInUse)
            {
                result.IsSuccess = false;
                result.Message = "串口未启用";
                return result;
            }


            if (_serialPort.IsOpen)
            {
                result.IsSuccess = false;
                result.Message = "串口已打开";
                return result;
            }


            try
            {
                _serialPort.PortName = _serialPortInfo.PortName;
                _serialPort.BaudRate = _serialPortInfo.BaudRate;
                _serialPort.DataBits = _serialPortInfo.DataBits;
                _serialPort.Parity = _serialPortInfo.Parity;
                //停止位不能设置为 =None，如果是None，不设置停止位
                if (_serialPortInfo.StopBits != StopBits.None)
                {
                    _serialPort.StopBits = _serialPortInfo.StopBits;
                }
                _serialPort.Open();
                result.IsSuccess = true;
            }
            catch (Exception e)
            {
                result.IsSuccess = false;
                result.Message = e.Message;
            }

            return result;
        }

        /// <summary>
        /// 多次关闭不会报错，为了优雅点，关闭前判断了串口状态
        /// </summary>
        /// <returns></returns>
        public OperateResult CloseSerialPort()
        {
            OperateResult result = new OperateResult();
            try
            {

                if (!_serialPortInfo.IsInUse)
                {
                    result.IsSuccess = false;
                    result.Message = "串口未启用";
                    return result;
                }
                if (_serialPort.IsOpen)
                {
                    _serialPort.Close();
                }
                result.IsSuccess = true;
            }
            catch (Exception e)
            {
                result.IsSuccess = false;
                result.Message = e.Message;
            }


            return result;
        }

        //发送默认数据
        public OperateResult<string> SendDefaultData()
        {
            OperateResult<string> result = SendData(_serialPortInfo.SendData);
            return result;
        }

        //发送数据
        public OperateResult<string> SendData(string data)
        {
            OperateResult<string> operateResult = new OperateResult<string>();
            if (!_serialPort.IsOpen)
            {
                operateResult.IsSuccess = false;
                operateResult.Message = "串口未打开";
                return operateResult;
            }
            RecDataFlag = false;
            RecData = "";
            try
            {

                switch (_serialPortInfo.DataType)
                {
                    case SerialPortDataType.Ascii:
                        _serialPort.Write(data);
                        operateResult.IsSuccess = true;
                        break;
                    case SerialPortDataType.Hex:
                        byte[] sendBytes = StrToToHexByte(data);
                        if (sendBytes.Length == 0)
                        {
                            operateResult.IsSuccess = false;
                            operateResult.Message = "非法的16进制字符串";
                            return operateResult;
                        }

                        _serialPort.Write(sendBytes, 0, sendBytes.Length);
                        operateResult.IsSuccess = true;
                        break;
                }



                if (_serialPortInfo.IsWaitData)
                {
                    Stopwatch sw = Stopwatch.StartNew();
                    while (true)
                    {
                        if (RecDataFlag)
                        {
                            break;
                        }

                        if (sw.ElapsedMilliseconds> WaitTime)
                        {
                            operateResult.IsSuccess = false;
                            operateResult.Message = WaitTime+"毫秒没有接收到返回值";
                            break;
                        }
                        Thread.Sleep(100);
                    }
                    operateResult.Content = RecData;
                }


            }
            catch (Exception e)
            {
                operateResult.IsSuccess = false;
                operateResult.Message = e.Message;
            }

            return operateResult;
        }

        //接收数据
        private void SerialPortPortDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                int len = _serialPort.BytesToRead;
                byte[] buffers = new byte[len];
                _serialPort.Read(buffers, 0, len);
                switch (_serialPortInfo.DataType)
                {
                    case SerialPortDataType.Ascii:
                        RecData = Encoding.ASCII.GetString(buffers);
                        break;
                    case SerialPortDataType.Hex:
                        RecData = string.Join(" ", buffers.Select(b => b.ToString("X2")).ToArray());
                        break;
                }

            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
            }



            RecDataFlag = true;

        }

        #endregion


        #region 其它方法

        /// <summary>
        /// 字符串转16进制格式,不够自动前面补零
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        private byte[] StrToToHexByte(string hexString)
        {
            int i;
            hexString = hexString.Replace(" ", "");//清除空格
            if ((hexString.Length % 2) != 0)//奇数个
            {
                byte[] returnBytes = new byte[(hexString.Length + 1) / 2];

                try
                {
                    for (i = 0; i < (hexString.Length - 1) / 2; i++)
                    {
                        returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
                    }
                    returnBytes[returnBytes.Length - 1] = Convert.ToByte(hexString.Substring(hexString.Length - 1, 1).PadLeft(2, '0'), 16);
                }
                catch
                {
                    return [];
                }

                return returnBytes;
            }
            else
            {
                byte[] returnBytes = new byte[(hexString.Length) / 2];
                try
                {
                    for (i = 0; i < returnBytes.Length; i++)
                    {
                        returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
                    }
                }
                catch
                {
                    return [];
                }
                return returnBytes;
            }
        }

        #endregion



    }


    
}
